Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use 1.5x growth factor for LocalVector #100944

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Nazarwadim
Copy link
Contributor

This is explained here godotengine/godot-proposals#7366.

Also, now if we use resize, as much memory as we need will be allocated if we increase the size by a value greater than 1.5 * capacity.

I tested in tps-demo and the memory usage difference is 2-3 megabytes. Did not notice the difference in FPS.

@RandomShaper
Copy link
Member

Makes sense!

I'd still ask for a couple more things before considering this complete:

  • Applying 1.5 factor also to CowData::_get_alloc_size().
  • Benchmarking.

@Nazarwadim
Copy link
Contributor Author

Applying 1.5 factor also to CowData::_get_alloc_size()

Well, there are two ways to do it. The first is to cache capacity. Another is to use a binary search among the Fibonacci numbers and choose a number slightly greater than or equal to the size.

Benchmarking.

What specific benchmarks are needed?

@RandomShaper
Copy link
Member

Applying 1.5 factor also to CowData::_get_alloc_size()

Well, there are two ways to do it. The first is to cache capacity. Another is to use a binary search among the Fibonacci numbers and choose a number slightly greater than or equal to the size.

Caching capacity sounds fine to me.

Benchmarking.

What specific benchmarks are needed?

Two possibilities (not necessarily exclusive):

  • Via the Godot benchmarks project, or a relevant subset of it.
  • Via a game project (Godot TPS demo or one of the platformers), paying attention to improvements in fps (or, well, frame time).

This change would ideally require benchmarking across a number of platforms, but, well, since we already understand why this new approach is theoretically beneficial, we would get enough peace of mind if we verify empircal benefits on a single platform. If only we had the mimalloc PR merged, we would be sure the change is a good for one platform as for the others.

@Nazarwadim
Copy link
Contributor Author

Caching capacity sounds fine to me.

static constexpr size_t REF_COUNT_OFFSET = 0;
static constexpr size_t SIZE_OFFSET = ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize) == 0) ? (REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) : ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) + alignof(USize) - ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize)));
static constexpr size_t DATA_OFFSET = ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t) == 0) ? (SIZE_OFFSET + sizeof(USize)) : ((SIZE_OFFSET + sizeof(USize)) + alignof(max_align_t) - ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t)));

When I tried to add capacity here, the size of the metadata became 32 bytes, not 24. It looks like ptr should be aligned by 16 bytes.

@Nazarwadim
Copy link
Contributor Author

Via a game project (Godot TPS demo or one of the platformers), paying attention to improvements in fps (or, well, frame time).

Tested in tps-demo with minimum graphics settings. Before that, the average was 408 fps, now it is 422. I tested in dynamics, where I used all the mechanics of the game and moved along the path to the reactor.
I did two tests, but kept the last one, because in the first test I did not think that the fps would be higher.

local_vector1.5-tps-demp-fps-test.ods

@hpvb
Copy link
Member

hpvb commented Jan 4, 2025

Same comment as the other PR: https://godbolt.org/z/Phc53zGq1

The floating point calculation isn't necessary

@Nazarwadim
Copy link
Contributor Author

From this comment: #101138 (comment)

So I will correct myself.

Using

capacity = capacity + ((1 + capacity) >> 1);

gives the same sequence https://godbolt.org/z/ssjT35ETW.

@Nazarwadim Nazarwadim force-pushed the LocalVector_use_1.5x_growth_factor branch 2 times, most recently from da33445 to b956449 Compare January 5, 2025 12:20
@Nazarwadim Nazarwadim requested a review from a team as a code owner January 5, 2025 12:20
@Nazarwadim Nazarwadim force-pushed the LocalVector_use_1.5x_growth_factor branch from b956449 to 0b135b3 Compare January 5, 2025 15:15
@RandomShaper
Copy link
Member

There are also some changes to inlining. Maybe this PR would better keep that out of its scope.

@Nazarwadim Nazarwadim force-pushed the LocalVector_use_1.5x_growth_factor branch from 0b135b3 to 77217fe Compare January 7, 2025 16:12
Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally (rebased on top of master 6f3cc27), it works as expected.

Benchmark

PC specifications
  • CPU: Intel Core i9-13900K
  • GPU: NVIDIA GeForce RTX 4090
  • RAM: 64 GB (2×32 GB DDR5-5800 C30)
  • SSD: Solidigm P44 Pro 2 TB
  • OS: Linux (Fedora 41)

Using a release export template with LTO.

a: master 6f3cc27
b: This PR

{
	"category": "C++ > Alloc",
	"name": "Deep Tree",
	"results": {
		"time": {
			"a": 146.8,
			"b": 145.6,
			"a_div_b": 1.0082417582417584
		}
	}
}
{
	"category": "C++ > Alloc",
	"name": "Duplicate",
	"results": {
		"time": {
			"a": 803.1,
			"b": 792.9,
			"a_div_b": 1.0128641695043512
		}
	}
}
{
	"category": "C++ > Alloc",
	"name": "Fragmentation",
	"results": {
		"time": {
			"a": 1973.0,
			"b": 1948.0,
			"a_div_b": 1.0128336755646816
		}
	}
}
{
	"category": "C++ > Alloc",
	"name": "Wide Tree",
	"results": {
		"time": {
			"a": 131.2,
			"b": 104.5,
			"a_div_b": 1.2555023923444975
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Color Array",
	"results": {
		"time": {
			"a": 54.02,
			"b": 51.16,
			"a_div_b": 1.0559030492572323
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Fill Loop",
	"results": {
		"time": {
			"a": 0.003,
			"b": 0.002,
			"a_div_b": 1.5
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Float 32 Array",
	"results": {
		"time": {
			"a": 56.02,
			"b": 54.29,
			"a_div_b": 1.031865905323264
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Float 64 Array",
	"results": {
		"time": {
			"a": 56.32,
			"b": 54.48,
			"a_div_b": 1.0337738619676946
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Int 32 Array",
	"results": {
		"time": {
			"a": 54.85,
			"b": 52.76,
			"a_div_b": 1.0396133434420016
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Int 64 Array",
	"results": {
		"time": {
			"a": 55.41,
			"b": 53.46,
			"a_div_b": 1.0364758698092031
		}
	}
}
{
	"category": "C++ > Array",
	"name": "String Array",
	"results": {
		"time": {
			"a": 592.9,
			"b": 590.4,
			"a_div_b": 1.0042344173441735
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Vector 2 Array",
	"results": {
		"time": {
			"a": 54.74,
			"b": 51.49,
			"a_div_b": 1.063119052243154
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Vector 3 Array",
	"results": {
		"time": {
			"a": 56.04,
			"b": 52.52,
			"a_div_b": 1.067022086824067
		}
	}
}
{
	"category": "C++ > Array",
	"name": "Vector 4 Array",
	"results": {
		"time": {
			"a": 52.97,
			"b": 51.11,
			"a_div_b": 1.0363920954803365
		}
	}
}
{
	"category": "C++ > Binary Trees",
	"name": "Binary Trees 13",
	"results": {
		"time": {
			"a": 23.07,
			"b": 23.16,
			"a_div_b": 0.9961139896373057
		}
	}
}
{
	"category": "C++ > Binary Trees",
	"name": "Binary Trees 15",
	"results": {
		"time": {
			"a": 110.5,
			"b": 110.8,
			"a_div_b": 0.9972924187725632
		}
	}
}
{
	"category": "C++ > Binary Trees",
	"name": "Binary Trees 18",
	"results": {
		"time": {
			"a": 1030.0,
			"b": 1028.0,
			"a_div_b": 1.0019455252918288
		}
	}
}
{
	"category": "C++ > Control",
	"name": "Control",
	"results": {
		"time": {
			"a": 0.004,
			"b": 0.004,
			"a_div_b": 1
		}
	}
}
{
	"category": "C++ > For Loop",
	"name": "Loop Add",
	"results": {
		"time": {
			"a": 0.002,
			"b": 0.003,
			"a_div_b": 0.6666666666666666
		}
	}
}
{
	"category": "C++ > For Loop",
	"name": "Loop Call",
	"results": {
		"time": {
			"a": 0.004,
			"b": 0.001,
			"a_div_b": 4
		}
	}
}
{
	"category": "C++ > Hello World",
	"name": "Hello World",
	"results": {
		"time": {
			"a": 0.01,
			"b": 0.008,
			"a_div_b": 1.25
		}
	}
}
{
	"category": "C++ > Lambda Performance",
	"name": "Lambda Call",
	"results": {
		"time": {
			"a": 0.001,
			"b": 0.001,
			"a_div_b": 1
		}
	}
}
{
	"category": "C++ > Mandelbrot Set",
	"name": "Mandelbrot Set",
	"results": {
		"time": {
			"a": 81.53,
			"b": 81.51,
			"a_div_b": 1.0002453686664212
		}
	}
}
{
	"category": "C++ > Merkle Trees",
	"name": "Merkle Trees 13",
	"results": {
		"time": {
			"a": 24.94,
			"b": 24.83,
			"a_div_b": 1.004430124848973
		}
	}
}
{
	"category": "C++ > Merkle Trees",
	"name": "Merkle Trees 15",
	"results": {
		"time": {
			"a": 117.5,
			"b": 120.2,
			"a_div_b": 0.9775374376039934
		}
	}
}
{
	"category": "C++ > Merkle Trees",
	"name": "Merkle Trees 18",
	"results": {
		"time": {
			"a": 1108.0,
			"b": 1116.0,
			"a_div_b": 0.992831541218638
		}
	}
}
{
	"category": "C++ > Nbody",
	"name": "Nbody 1 000 000",
	"results": {
		"time": {
			"a": 29.78,
			"b": 29.74,
			"a_div_b": 1.0013449899125757
		}
	}
}
{
	"category": "C++ > Nbody",
	"name": "Nbody 500 000",
	"results": {
		"time": {
			"a": 14.9,
			"b": 14.88,
			"a_div_b": 1.0013440860215053
		}
	}
}
{
	"category": "C++ > Spectral Norm",
	"name": "Spectral Norm 100",
	"results": {
		"time": {
			"a": 0.302,
			"b": 0.303,
			"a_div_b": 0.9966996699669967
		}
	}
}
{
	"category": "C++ > Spectral Norm",
	"name": "Spectral Norm 1000",
	"results": {
		"time": {
			"a": 29.21,
			"b": 29.15,
			"a_div_b": 1.0020583190394512
		}
	}
}
{
	"category": "C++ > Spectral Norm",
	"name": "Spectral Norm 500",
	"results": {
		"time": {
			"a": 7.375,
			"b": 7.298,
			"a_div_b": 1.0105508358454371
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Md 5 Buffer Empty",
	"results": {
		"time": {
			"a": 101.4,
			"b": 99.71,
			"a_div_b": 1.016949152542373
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Md 5 Buffer Non Empty",
	"results": {
		"time": {
			"a": 396.5,
			"b": 397.0,
			"a_div_b": 0.9987405541561712
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Md 5 Text Empty",
	"results": {
		"time": {
			"a": 102.1,
			"b": 102.6,
			"a_div_b": 0.9951267056530214
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Md 5 Text Non Empty",
	"results": {
		"time": {
			"a": 398.8,
			"b": 399.5,
			"a_div_b": 0.9982478097622027
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 1 Buffer Empty",
	"results": {
		"time": {
			"a": 90.05,
			"b": 89.07,
			"a_div_b": 1.0110025822386888
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 1 Buffer Non Empty",
	"results": {
		"time": {
			"a": 359.9,
			"b": 359.1,
			"a_div_b": 1.0022277917014757
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 1 Text Empty",
	"results": {
		"time": {
			"a": 96.48,
			"b": 93.26,
			"a_div_b": 1.0345271284580742
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 1 Text Non Empty",
	"results": {
		"time": {
			"a": 364.6,
			"b": 366.3,
			"a_div_b": 0.9953589953589954
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 256 Buffer Empty",
	"results": {
		"time": {
			"a": 167.3,
			"b": 165.1,
			"a_div_b": 1.0133252574197458
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 256 Buffer Non Empty",
	"results": {
		"time": {
			"a": 645.5,
			"b": 645.8,
			"a_div_b": 0.9995354598947043
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 256 Text Empty",
	"results": {
		"time": {
			"a": 173.4,
			"b": 174.5,
			"a_div_b": 0.9936962750716333
		}
	}
}
{
	"category": "C++ > String Checksum",
	"name": "Sha 256 Text Non Empty",
	"results": {
		"time": {
			"a": 658.7,
			"b": 653.6,
			"a_div_b": 1.0078029375764994
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Complex Variable Concatenate",
	"results": {
		"time": {
			"a": 1305.0,
			"b": 1278.0,
			"a_div_b": 1.0211267605633803
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Complex Variable Method",
	"results": {
		"time": {
			"a": 2087.0,
			"b": 2054.0,
			"a_div_b": 1.0160662122687438
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Complex Variable Percent",
	"results": {
		"time": {
			"a": 1576.0,
			"b": 1563.0,
			"a_div_b": 1.0083173384516955
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "No Op Constant Method",
	"results": {
		"time": {
			"a": 115.3,
			"b": 113.6,
			"a_div_b": 1.0149647887323945
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Simple Constant Concatenate",
	"results": {
		"time": {
			"a": 166.6,
			"b": 168.0,
			"a_div_b": 0.9916666666666666
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Simple Constant Method",
	"results": {
		"time": {
			"a": 404.5,
			"b": 402.1,
			"a_div_b": 1.0059686645113155
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Simple Constant Method Constant Dict",
	"results": {
		"time": {
			"a": 250.9,
			"b": 252.1,
			"a_div_b": 0.9952399841332805
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Simple Constant Percent",
	"results": {
		"time": {
			"a": 259.0,
			"b": 261.5,
			"a_div_b": 0.9904397705544933
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Simple Variable Concatenate",
	"results": {
		"time": {
			"a": 169.5,
			"b": 167.7,
			"a_div_b": 1.0107334525939178
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Simple Variable Method",
	"results": {
		"time": {
			"a": 406.6,
			"b": 405.9,
			"a_div_b": 1.0017245627001725
		}
	}
}
{
	"category": "C++ > String Format",
	"name": "Simple Variable Percent",
	"results": {
		"time": {
			"a": 258.7,
			"b": 261.9,
			"a_div_b": 0.9877815960290187
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Begins With",
	"results": {
		"time": {
			"a": 37.49,
			"b": 37.34,
			"a_div_b": 1.0040171397964648
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Bigrams",
	"results": {
		"time": {
			"a": 327.8,
			"b": 329.4,
			"a_div_b": 0.995142683667274
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Capitalize",
	"results": {
		"time": {
			"a": 664.9,
			"b": 666.9,
			"a_div_b": 0.9970010496326286
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Casecmp To",
	"results": {
		"time": {
			"a": 37.49,
			"b": 37.83,
			"a_div_b": 0.9910124240021149
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Contains",
	"results": {
		"time": {
			"a": 37.08,
			"b": 36.85,
			"a_div_b": 1.0062415196743555
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Count",
	"results": {
		"time": {
			"a": 61.9,
			"b": 60.71,
			"a_div_b": 1.0196013836270794
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Countn",
	"results": {
		"time": {
			"a": 217.8,
			"b": 216.7,
			"a_div_b": 1.0050761421319798
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Ends With",
	"results": {
		"time": {
			"a": 37.94,
			"b": 37.36,
			"a_div_b": 1.015524625267666
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Find",
	"results": {
		"time": {
			"a": 37.35,
			"b": 36.97,
			"a_div_b": 1.0102786042737355
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Findn",
	"results": {
		"time": {
			"a": 59.05,
			"b": 58.63,
			"a_div_b": 1.0071635681391777
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Get Slice",
	"results": {
		"time": {
			"a": 71.27,
			"b": 70.33,
			"a_div_b": 1.0133655623489264
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Get Slice Count",
	"results": {
		"time": {
			"a": 41.11,
			"b": 40.79,
			"a_div_b": 1.0078450600637412
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Humanize Size",
	"results": {
		"time": {
			"a": 501.2,
			"b": 496.4,
			"a_div_b": 1.0096696212731668
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Insert",
	"results": {
		"time": {
			"a": 64.77,
			"b": 65.08,
			"a_div_b": 0.9952366318377381
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Is Valid Filename",
	"results": {
		"time": {
			"a": 34.54,
			"b": 34.64,
			"a_div_b": 0.9971131639722863
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Lpad",
	"results": {
		"time": {
			"a": 168.5,
			"b": 167.3,
			"a_div_b": 1.007172743574417
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Naturalnocasecmp To",
	"results": {
		"time": {
			"a": 38.35,
			"b": 38.35,
			"a_div_b": 1
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Nocasecmp To",
	"results": {
		"time": {
			"a": 57.66,
			"b": 57.54,
			"a_div_b": 1.0020855057351408
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Pad Decimals",
	"results": {
		"time": {
			"a": 302.2,
			"b": 305.5,
			"a_div_b": 0.9891980360065467
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Pad Decimals Pre Constructed",
	"results": {
		"time": {
			"a": 57.68,
			"b": 57.52,
			"a_div_b": 1.0027816411682893
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Pad Zeros",
	"results": {
		"time": {
			"a": 210.9,
			"b": 218.6,
			"a_div_b": 0.9647758462946021
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Pad Zeros Pre Constructed",
	"results": {
		"time": {
			"a": 125.1,
			"b": 124.7,
			"a_div_b": 1.0032076984763432
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Rfind",
	"results": {
		"time": {
			"a": 39.93,
			"b": 40.37,
			"a_div_b": 0.9891008174386922
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Rfindn",
	"results": {
		"time": {
			"a": 151.5,
			"b": 151.1,
			"a_div_b": 1.0026472534745203
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Rpad",
	"results": {
		"time": {
			"a": 124.1,
			"b": 124.5,
			"a_div_b": 0.9967871485943774
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Rsplit",
	"results": {
		"time": {
			"a": 245.6,
			"b": 213.5,
			"a_div_b": 1.1503512880562061
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Similarity",
	"results": {
		"time": {
			"a": 40.92,
			"b": 42.01,
			"a_div_b": 0.974053796715068
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Simplify Path",
	"results": {
		"time": {
			"a": 690.8,
			"b": 691.3,
			"a_div_b": 0.9992767250108491
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Split",
	"results": {
		"time": {
			"a": 239.5,
			"b": 206.6,
			"a_div_b": 1.159244917715392
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Split Floats",
	"results": {
		"time": {
			"a": 155.6,
			"b": 154.9,
			"a_div_b": 1.0045190445448675
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Substr",
	"results": {
		"time": {
			"a": 47.83,
			"b": 48.01,
			"a_div_b": 0.9962507810872735
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Camel Case",
	"results": {
		"time": {
			"a": 416.3,
			"b": 416.0,
			"a_div_b": 1.0007211538461538
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Lower",
	"results": {
		"time": {
			"a": 147.6,
			"b": 147.8,
			"a_div_b": 0.9986468200270635
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Pascal Case",
	"results": {
		"time": {
			"a": 725.8,
			"b": 712.9,
			"a_div_b": 1.0180951045027353
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Snake Case",
	"results": {
		"time": {
			"a": 597.7,
			"b": 590.5,
			"a_div_b": 1.0121930567315836
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Utf 16 Buffer",
	"results": {
		"time": {
			"a": 67.48,
			"b": 67.25,
			"a_div_b": 1.0034200743494424
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Utf 32 Buffer",
	"results": {
		"time": {
			"a": 46.86,
			"b": 48.45,
			"a_div_b": 0.9671826625386997
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Utf 8 Buffer",
	"results": {
		"time": {
			"a": 66.14,
			"b": 66.21,
			"a_div_b": 0.9989427578915573
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "To Wchar Buffer",
	"results": {
		"time": {
			"a": 46.89,
			"b": 45.94,
			"a_div_b": 1.020679146713104
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Uri Decode",
	"results": {
		"time": {
			"a": 220.1,
			"b": 222.9,
			"a_div_b": 0.9874383131449079
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Uri Encode",
	"results": {
		"time": {
			"a": 231.7,
			"b": 231.1,
			"a_div_b": 1.0025962786672435
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Validate Filename",
	"results": {
		"time": {
			"a": 212.1,
			"b": 211.5,
			"a_div_b": 1.0028368794326241
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Validate Node Name",
	"results": {
		"time": {
			"a": 73.13,
			"b": 77.1,
			"a_div_b": 0.9485084306095979
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Xml Escape",
	"results": {
		"time": {
			"a": 197.7,
			"b": 202.0,
			"a_div_b": 0.9787128712871287
		}
	}
}
{
	"category": "C++ > String Manipulation",
	"name": "Xml Unescape",
	"results": {
		"time": {
			"a": 53.91,
			"b": 54.03,
			"a_div_b": 0.9977790116601887
		}
	}
}
{
	"category": "Animation > Animated Models",
	"name": "Animation Blend Tree 100",
	"results": {
		"render_cpu": {
			"a": 0.8908,
			"b": 0.8243,
			"a_div_b": 1.0806745117069028
		},
		"render_gpu": {
			"a": 0.5778,
			"b": 0.5694,
			"a_div_b": 1.0147523709167545
		},
		"time": {
			"a": 0.014,
			"b": 0.009,
			"a_div_b": 1.5555555555555558
		}
	}
}
{
	"category": "Animation > Animated Models",
	"name": "Animation State Machine 1000",
	"results": {
		"render_cpu": {
			"a": 4.349,
			"b": 4.273,
			"a_div_b": 1.0177860987596539
		},
		"render_gpu": {
			"a": 3.653,
			"b": 4.46,
			"a_div_b": 0.8190582959641256
		},
		"time": {
			"a": 0.097,
			"b": 0.019,
			"a_div_b": 5.105263157894737
		}
	}
}
{
	"category": "Animation > Tween",
	"name": "Animate 1000 Tween Methods",
	"results": {
		"render_cpu": {
			"a": 0.05282,
			"b": 0.0531,
			"a_div_b": 0.9947269303201506
		},
		"time": {
			"a": 2.171,
			"b": 2.237,
			"a_div_b": 0.9704962002682163
		}
	}
}
{
	"category": "Animation > Tween",
	"name": "Tween 100 Properties",
	"results": {
		"render_cpu": {
			"a": 0.009509,
			"b": 0.009756,
			"a_div_b": 0.9746822468224682
		},
		"time": {
			"a": 0.339,
			"b": 0.222,
			"a_div_b": 1.5270270270270272
		}
	}
}
{
	"category": "Asset Import Export > Runtime",
	"name": "Export Gltf",
	"results": {
		"time": {
			"a": 53.59,
			"b": 39.03,
			"a_div_b": 1.3730463745836536
		}
	}
}
{
	"category": "Asset Import Export > Runtime",
	"name": "Import Fbx",
	"results": {
		"time": {
			"a": 368.6,
			"b": 362.1,
			"a_div_b": 1.0179508423087544
		}
	}
}
{
	"category": "Asset Import Export > Runtime",
	"name": "Import Gltf",
	"results": {
		"time": {
			"a": 17.18,
			"b": 21.4,
			"a_div_b": 0.8028037383177571
		}
	}
}
{
	"category": "Asset Import Export > Runtime",
	"name": "Import Ogg Audio",
	"results": {
		"time": {
			"a": 2.762,
			"b": 2.634,
			"a_div_b": 1.0485952923310555
		}
	}
}
{
	"category": "Asset Import Export > Runtime",
	"name": "Import Webp Images",
	"results": {
		"time": {
			"a": 309.2,
			"b": 305.7,
			"a_div_b": 1.0114491331370625
		}
	}
}
{
	"category": "Core > Array",
	"name": "Append Array",
	"results": {
		"time": {
			"a": 152.3,
			"b": 146.2,
			"a_div_b": 1.0417236662106704
		}
	}
}
{
	"category": "Core > Array",
	"name": "Bsearch",
	"results": {
		"time": {
			"a": 54.24,
			"b": 54.78,
			"a_div_b": 0.9901423877327492
		}
	}
}
{
	"category": "Core > Array",
	"name": "Fill",
	"results": {
		"time": {
			"a": 38.05,
			"b": 38.99,
			"a_div_b": 0.9758912541677351
		}
	}
}
{
	"category": "Core > Array",
	"name": "Reverse",
	"results": {
		"time": {
			"a": 19.23,
			"b": 17.0,
			"a_div_b": 1.1311764705882352
		}
	}
}
{
	"category": "Core > Callable",
	"name": "Function Callable",
	"results": {
		"time": {
			"a": 194.5,
			"b": 204.1,
			"a_div_b": 0.9529642332190104
		}
	}
}
{
	"category": "Core > Callable",
	"name": "Lambda Inline Callable",
	"results": {
		"time": {
			"a": 213.9,
			"b": 218.8,
			"a_div_b": 0.9776051188299817
		}
	}
}
{
	"category": "Core > Callable",
	"name": "Lambda Variable Callable",
	"results": {
		"time": {
			"a": 56.47,
			"b": 55.14,
			"a_div_b": 1.024120420747189
		}
	}
}
{
	"category": "Core > Config File",
	"name": "Load",
	"results": {
		"time": {
			"a": 19.23,
			"b": 19.19,
			"a_div_b": 1.0020844189682125
		}
	}
}
{
	"category": "Core > Config File",
	"name": "Load With Password",
	"results": {
		"time": {
			"a": 20.65,
			"b": 25.88,
			"a_div_b": 0.7979134466769706
		}
	}
}
{
	"category": "Core > Config File",
	"name": "Save",
	"results": {
		"time": {
			"a": 23.11,
			"b": 23.39,
			"a_div_b": 0.9880290722530995
		}
	}
}
{
	"category": "Core > Config File",
	"name": "Save With Password",
	"results": {
		"time": {
			"a": 23.04,
			"b": 23.25,
			"a_div_b": 0.9909677419354839
		}
	}
}
{
	"category": "Core > Crypto",
	"name": "Generate 1g Random Bytes 1k At A Time",
	"results": {
		"time": {
			"a": 1442.0,
			"b": 1450.0,
			"a_div_b": 0.9944827586206897
		}
	}
}
{
	"category": "Core > Crypto",
	"name": "Generate 1m Random Bytes 10 At A Time",
	"results": {
		"time": {
			"a": 6484.0,
			"b": 6499.0,
			"a_div_b": 0.9976919526080935
		}
	}
}
{
	"category": "Core > Crypto",
	"name": "Generate Rsa 2048",
	"results": {
		"time": {
			"a": 63.01,
			"b": 42.57,
			"a_div_b": 1.4801503406154568
		}
	}
}
{
	"category": "Core > Crypto",
	"name": "Generate Rsa 4096",
	"results": {
		"time": {
			"a": 1076.0,
			"b": 1230.0,
			"a_div_b": 0.8747967479674796
		}
	}
}
{
	"category": "Core > Node Path",
	"name": "Create",
	"results": {
		"time": {
			"a": 12.0,
			"b": 13.34,
			"a_div_b": 0.8995502248875562
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "12 Threads Full Contention",
	"results": {
		"time": {
			"a": 699.0,
			"b": 886.0,
			"a_div_b": 0.7889390519187359
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "12 Threads Half Contention",
	"results": {
		"time": {
			"a": 360.1,
			"b": 453.6,
			"a_div_b": 0.7938712522045855
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "12 Threads Little Contention",
	"results": {
		"time": {
			"a": 77.72,
			"b": 99.05,
			"a_div_b": 0.7846542150429077
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "12 Threads Slope Contention",
	"results": {
		"time": {
			"a": 386.8,
			"b": 457.6,
			"a_div_b": 0.8452797202797203
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "2 Threads Full Contention",
	"results": {
		"time": {
			"a": 55.13,
			"b": 54.62,
			"a_div_b": 1.0093372391065545
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "2 Threads Half Contention",
	"results": {
		"time": {
			"a": 35.21,
			"b": 34.54,
			"a_div_b": 1.0193977996525767
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "2 Threads Little Contention",
	"results": {
		"time": {
			"a": 17.54,
			"b": 16.91,
			"a_div_b": 1.0372560615020696
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "4 Threads Full Contention",
	"results": {
		"time": {
			"a": 148.7,
			"b": 170.6,
			"a_div_b": 0.8716295427901524
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "4 Threads Half Contention",
	"results": {
		"time": {
			"a": 81.81,
			"b": 91.88,
			"a_div_b": 0.8904005224205486
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "4 Threads Little Contention",
	"results": {
		"time": {
			"a": 28.06,
			"b": 30.14,
			"a_div_b": 0.9309887193098871
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "4 Threads Slope Contention",
	"results": {
		"time": {
			"a": 112.3,
			"b": 121.4,
			"a_div_b": 0.9250411861614497
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "8 Threads Full Contention",
	"results": {
		"time": {
			"a": 383.1,
			"b": 435.5,
			"a_div_b": 0.8796785304247992
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "8 Threads Half Contention",
	"results": {
		"time": {
			"a": 204.8,
			"b": 230.6,
			"a_div_b": 0.8881179531656549
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "8 Threads Little Contention",
	"results": {
		"time": {
			"a": 47.66,
			"b": 56.71,
			"a_div_b": 0.8404161523540821
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "8 Threads Slope Contention",
	"results": {
		"time": {
			"a": 232.7,
			"b": 262.6,
			"a_div_b": 0.886138613861386
		}
	}
}
{
	"category": "Core > Object Db",
	"name": "Single",
	"results": {
		"time": {
			"a": 16.43,
			"b": 14.76,
			"a_div_b": 1.1131436314363143
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Global Scope Randf",
	"results": {
		"time": {
			"a": 64.11,
			"b": 60.03,
			"a_div_b": 1.0679660169915042
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Global Scope Randf Range",
	"results": {
		"time": {
			"a": 96.48,
			"b": 106.6,
			"a_div_b": 0.9050656660412759
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Global Scope Randfn",
	"results": {
		"time": {
			"a": 302.5,
			"b": 304.8,
			"a_div_b": 0.9924540682414698
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Global Scope Randi",
	"results": {
		"time": {
			"a": 59.23,
			"b": 56.33,
			"a_div_b": 1.051482336232913
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Global Scope Randi Range",
	"results": {
		"time": {
			"a": 81.96,
			"b": 82.31,
			"a_div_b": 0.9957477827724456
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Global Scope Randomize",
	"results": {
		"time": {
			"a": 323.7,
			"b": 325.5,
			"a_div_b": 0.9944700460829493
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Randf",
	"results": {
		"time": {
			"a": 71.75,
			"b": 72.56,
			"a_div_b": 0.9888368246968026
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Randf Range",
	"results": {
		"time": {
			"a": 90.6,
			"b": 93.04,
			"a_div_b": 0.9737747205503008
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Randfn",
	"results": {
		"time": {
			"a": 252.3,
			"b": 252.5,
			"a_div_b": 0.9992079207920792
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Randi",
	"results": {
		"time": {
			"a": 47.37,
			"b": 48.09,
			"a_div_b": 0.9850280723643168
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Randi Range",
	"results": {
		"time": {
			"a": 67.98,
			"b": 68.21,
			"a_div_b": 0.9966280604017008
		}
	}
}
{
	"category": "Core > Random Number Generator",
	"name": "Randomize",
	"results": {
		"time": {
			"a": 352.5,
			"b": 352.9,
			"a_div_b": 0.9988665344290167
		}
	}
}
{
	"category": "Core > Signal",
	"name": "Emission Params 0",
	"results": {
		"time": {
			"a": 123.9,
			"b": 123.3,
			"a_div_b": 1.0048661800486618
		}
	}
}
{
	"category": "Core > Signal",
	"name": "Emission Params 1",
	"results": {
		"time": {
			"a": 129.7,
			"b": 124.2,
			"a_div_b": 1.0442834138486312
		}
	}
}
{
	"category": "Core > Signal",
	"name": "Emission Params 10",
	"results": {
		"time": {
			"a": 139.4,
			"b": 140.6,
			"a_div_b": 0.9914651493598863
		}
	}
}
{
	"category": "Core > String Name",
	"name": "Create",
	"results": {
		"time": {
			"a": 12.46,
			"b": 12.47,
			"a_div_b": 0.9991980753809142
		}
	}
}
{
	"category": "Gdscript > Alloc",
	"name": "Deep Tree",
	"results": {
		"time": {
			"a": 98.73,
			"b": 125.0,
			"a_div_b": 0.78984
		}
	}
}
{
	"category": "Gdscript > Alloc",
	"name": "Duplicate",
	"results": {
		"time": {
			"a": 798.7,
			"b": 794.0,
			"a_div_b": 1.005919395465995
		}
	}
}
{
	"category": "Gdscript > Alloc",
	"name": "Fragmentation",
	"results": {
		"time": {
			"a": 1719.0,
			"b": 1716.0,
			"a_div_b": 1.0017482517482517
		}
	}
}
{
	"category": "Gdscript > Alloc",
	"name": "Wide Tree",
	"results": {
		"time": {
			"a": 97.59,
			"b": 97.63,
			"a_div_b": 0.9995902898699172
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Fill Loop",
	"results": {
		"time": {
			"a": 166.2,
			"b": 166.4,
			"a_div_b": 0.9987980769230769
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Fill Method",
	"results": {
		"time": {
			"a": 85.17,
			"b": 81.35,
			"a_div_b": 1.0469575906576523
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed Color Array",
	"results": {
		"time": {
			"a": 87.19,
			"b": 86.52,
			"a_div_b": 1.0077438742487286
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed Float 32 Array",
	"results": {
		"time": {
			"a": 62.79,
			"b": 62.31,
			"a_div_b": 1.0077034183919114
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed Float 64 Array",
	"results": {
		"time": {
			"a": 63.41,
			"b": 63.13,
			"a_div_b": 1.0044352922540787
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed Int 32 Array",
	"results": {
		"time": {
			"a": 50.15,
			"b": 49.07,
			"a_div_b": 1.0220093743631546
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed Int 64 Array",
	"results": {
		"time": {
			"a": 50.01,
			"b": 48.91,
			"a_div_b": 1.0224902882846043
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed String Array",
	"results": {
		"time": {
			"a": 355.5,
			"b": 355.0,
			"a_div_b": 1.0014084507042254
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed Vector 2 Array",
	"results": {
		"time": {
			"a": 72.71,
			"b": 73.95,
			"a_div_b": 0.983231913455037
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Packed Vector 3 Array",
	"results": {
		"time": {
			"a": 90.55,
			"b": 88.45,
			"a_div_b": 1.0237422272470322
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Typed Color Array",
	"results": {
		"time": {
			"a": 130.9,
			"b": 118.4,
			"a_div_b": 1.1055743243243243
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Typed Float Array",
	"results": {
		"time": {
			"a": 104.3,
			"b": 93.97,
			"a_div_b": 1.1099287006491434
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Typed Int Array",
	"results": {
		"time": {
			"a": 114.6,
			"b": 88.6,
			"a_div_b": 1.2934537246049662
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Typed String Array",
	"results": {
		"time": {
			"a": 418.4,
			"b": 411.0,
			"a_div_b": 1.0180048661800487
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Typed Vector 2 Array",
	"results": {
		"time": {
			"a": 119.9,
			"b": 109.9,
			"a_div_b": 1.0909918107370336
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Typed Vector 3 Array",
	"results": {
		"time": {
			"a": 131.2,
			"b": 116.0,
			"a_div_b": 1.1310344827586205
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Untyped Color Array",
	"results": {
		"time": {
			"a": 202.1,
			"b": 190.4,
			"a_div_b": 1.0614495798319328
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Untyped Float Array",
	"results": {
		"time": {
			"a": 173.3,
			"b": 158.5,
			"a_div_b": 1.0933753943217666
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Untyped Int Array",
	"results": {
		"time": {
			"a": 172.1,
			"b": 159.3,
			"a_div_b": 1.0803515379786566
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Untyped String Array",
	"results": {
		"time": {
			"a": 486.5,
			"b": 484.4,
			"a_div_b": 1.004335260115607
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Untyped Vector 2 Array",
	"results": {
		"time": {
			"a": 193.1,
			"b": 179.6,
			"a_div_b": 1.0751670378619154
		}
	}
}
{
	"category": "Gdscript > Array",
	"name": "Untyped Vector 3 Array",
	"results": {
		"time": {
			"a": 203.6,
			"b": 189.0,
			"a_div_b": 1.0772486772486771
		}
	}
}
{
	"category": "Gdscript > Binary Trees",
	"name": "Binary Trees 13",
	"results": {
		"time": {
			"a": 323.3,
			"b": 321.2,
			"a_div_b": 1.00653798256538
		}
	}
}
{
	"category": "Gdscript > Binary Trees",
	"name": "Binary Trees 15",
	"results": {
		"time": {
			"a": 1533.0,
			"b": 1539.0,
			"a_div_b": 0.9961013645224172
		}
	}
}
{
	"category": "Gdscript > Control",
	"name": "Control",
	"results": {
		"time": {
			"a": 0.004,
			"b": 0.004,
			"a_div_b": 1
		}
	}
}
{
	"category": "Gdscript > For Loop",
	"name": "For Loop Add",
	"results": {
		"time": {
			"a": 4.718,
			"b": 4.81,
			"a_div_b": 0.980873180873181
		}
	}
}
{
	"category": "Gdscript > For Loop",
	"name": "For Loop Call",
	"results": {
		"time": {
			"a": 32.89,
			"b": 32.66,
			"a_div_b": 1.007042253521127
		}
	}
}
{
	"category": "Gdscript > Hello World",
	"name": "Hello World",
	"results": {
		"time": {
			"a": 0.011,
			"b": 0.011,
			"a_div_b": 1
		}
	}
}
{
	"category": "Gdscript > Lambda Performance",
	"name": "Lambda Call",
	"results": {
		"time": {
			"a": 27.67,
			"b": 27.94,
			"a_div_b": 0.990336435218325
		}
	}
}
{
	"category": "Gdscript > Mandelbrot Set",
	"name": "Mandelbrot Set",
	"results": {
		"time": {
			"a": 1593.0,
			"b": 1625.0,
			"a_div_b": 0.9803076923076923
		}
	}
}
{
	"category": "Gdscript > Merkle Trees",
	"name": "Merkle Trees 13",
	"results": {
		"time": {
			"a": 876.4,
			"b": 872.5,
			"a_div_b": 1.0044699140401145
		}
	}
}
{
	"category": "Gdscript > Merkle Trees",
	"name": "Merkle Trees 15",
	"results": {
		"time": {
			"a": 4305.0,
			"b": 4523.0,
			"a_div_b": 0.9518019013928808
		}
	}
}
{
	"category": "Gdscript > Nbody",
	"name": "Nbody 1 000 000",
	"results": {
		"time": {
			"a": 3724.0,
			"b": 3894.0,
			"a_div_b": 0.9563430919363123
		}
	}
}
{
	"category": "Gdscript > Nbody",
	"name": "Nbody 500 000",
	"results": {
		"time": {
			"a": 1868.0,
			"b": 1947.0,
			"a_div_b": 0.9594247560349255
		}
	}
}
{
	"category": "Gdscript > Spectral Norm",
	"name": "Spectral Norm 100",
	"results": {
		"time": {
			"a": 28.8,
			"b": 28.52,
			"a_div_b": 1.0098176718092566
		}
	}
}
{
	"category": "Gdscript > Spectral Norm",
	"name": "Spectral Norm 1000",
	"results": {
		"time": {
			"a": 2854.0,
			"b": 2817.0,
			"a_div_b": 1.0131345402910898
		}
	}
}
{
	"category": "Gdscript > Spectral Norm",
	"name": "Spectral Norm 500",
	"results": {
		"time": {
			"a": 714.0,
			"b": 706.4,
			"a_div_b": 1.0107587768969424
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Md 5 Buffer Empty",
	"results": {
		"time": {
			"a": 115.9,
			"b": 116.2,
			"a_div_b": 0.9974182444061962
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Md 5 Buffer Non Empty",
	"results": {
		"time": {
			"a": 417.1,
			"b": 415.7,
			"a_div_b": 1.0033678133269186
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Md 5 Text Empty",
	"results": {
		"time": {
			"a": 101.9,
			"b": 102.3,
			"a_div_b": 0.9960899315738027
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Md 5 Text Non Empty",
	"results": {
		"time": {
			"a": 401.9,
			"b": 401.8,
			"a_div_b": 1.0002488800398208
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 1 Buffer Empty",
	"results": {
		"time": {
			"a": 106.0,
			"b": 105.7,
			"a_div_b": 1.0028382213812677
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 1 Buffer Non Empty",
	"results": {
		"time": {
			"a": 379.2,
			"b": 382.3,
			"a_div_b": 0.9918911849332984
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 1 Text Empty",
	"results": {
		"time": {
			"a": 94.57,
			"b": 97.23,
			"a_div_b": 0.9726421886249099
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 1 Text Non Empty",
	"results": {
		"time": {
			"a": 368.5,
			"b": 379.8,
			"a_div_b": 0.9702474986835176
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 256 Buffer Empty",
	"results": {
		"time": {
			"a": 188.8,
			"b": 182.1,
			"a_div_b": 1.0367929708951127
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 256 Buffer Non Empty",
	"results": {
		"time": {
			"a": 664.1,
			"b": 671.0,
			"a_div_b": 0.9897168405365127
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 256 Text Empty",
	"results": {
		"time": {
			"a": 170.2,
			"b": 173.3,
			"a_div_b": 0.9821119446047315
		}
	}
}
{
	"category": "Gdscript > String Checksum",
	"name": "Sha 256 Text Non Empty",
	"results": {
		"time": {
			"a": 659.9,
			"b": 668.9,
			"a_div_b": 0.986545074002093
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Complex Variable Concatenate",
	"results": {
		"time": {
			"a": 1104.0,
			"b": 1109.0,
			"a_div_b": 0.9954914337240758
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Complex Variable Method",
	"results": {
		"time": {
			"a": 1741.0,
			"b": 1790.0,
			"a_div_b": 0.9726256983240223
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Complex Variable Percent",
	"results": {
		"time": {
			"a": 1370.0,
			"b": 1388.0,
			"a_div_b": 0.9870317002881844
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "No Op Constant Method",
	"results": {
		"time": {
			"a": 101.0,
			"b": 98.32,
			"a_div_b": 1.0272579332790888
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Simple Constant Concatenate",
	"results": {
		"time": {
			"a": 2.036,
			"b": 2.072,
			"a_div_b": 0.9826254826254827
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Simple Constant Method",
	"results": {
		"time": {
			"a": 359.9,
			"b": 366.3,
			"a_div_b": 0.9825279825279825
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Simple Constant Method Constant Dict",
	"results": {
		"time": {
			"a": 234.3,
			"b": 247.5,
			"a_div_b": 0.9466666666666668
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Simple Constant Percent",
	"results": {
		"time": {
			"a": 2.091,
			"b": 2.216,
			"a_div_b": 0.9435920577617328
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Simple Variable Concatenate",
	"results": {
		"time": {
			"a": 118.2,
			"b": 117.6,
			"a_div_b": 1.0051020408163267
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Simple Variable Method",
	"results": {
		"time": {
			"a": 358.2,
			"b": 355.6,
			"a_div_b": 1.0073115860517434
		}
	}
}
{
	"category": "Gdscript > String Format",
	"name": "Simple Variable Percent",
	"results": {
		"time": {
			"a": 242.9,
			"b": 241.4,
			"a_div_b": 1.0062137531068767
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Begins With",
	"results": {
		"time": {
			"a": 7.396,
			"b": 7.175,
			"a_div_b": 1.030801393728223
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Bigrams",
	"results": {
		"time": {
			"a": 361.6,
			"b": 360.9,
			"a_div_b": 1.001939595455805
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Capitalize",
	"results": {
		"time": {
			"a": 652.5,
			"b": 640.6,
			"a_div_b": 1.0185763346862315
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Casecmp To",
	"results": {
		"time": {
			"a": 7.004,
			"b": 6.475,
			"a_div_b": 1.0816988416988418
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Contains",
	"results": {
		"time": {
			"a": 5.529,
			"b": 5.316,
			"a_div_b": 1.0400677200902935
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Contains Gdscript In",
	"results": {
		"time": {
			"a": 2.025,
			"b": 2.276,
			"a_div_b": 0.8897188049209139
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Count",
	"results": {
		"time": {
			"a": 51.32,
			"b": 52.65,
			"a_div_b": 0.9747388414055081
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Countn",
	"results": {
		"time": {
			"a": 204.1,
			"b": 203.8,
			"a_div_b": 1.0014720314033365
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Ends With",
	"results": {
		"time": {
			"a": 6.984,
			"b": 7.911,
			"a_div_b": 0.8828213879408419
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Find",
	"results": {
		"time": {
			"a": 28.37,
			"b": 28.19,
			"a_div_b": 1.0063852429939695
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Findn",
	"results": {
		"time": {
			"a": 48.43,
			"b": 46.55,
			"a_div_b": 1.0403866809881848
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Get Slice",
	"results": {
		"time": {
			"a": 36.93,
			"b": 48.41,
			"a_div_b": 0.7628589134476348
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Get Slice Count",
	"results": {
		"time": {
			"a": 15.09,
			"b": 13.6,
			"a_div_b": 1.1095588235294118
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Humanize Size",
	"results": {
		"time": {
			"a": 499.2,
			"b": 498.3,
			"a_div_b": 1.0018061408789884
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Insert",
	"results": {
		"time": {
			"a": 30.62,
			"b": 30.48,
			"a_div_b": 1.0045931758530184
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Is Valid Filename",
	"results": {
		"time": {
			"a": 20.89,
			"b": 21.44,
			"a_div_b": 0.9743470149253731
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Lpad",
	"results": {
		"time": {
			"a": 123.8,
			"b": 121.1,
			"a_div_b": 1.022295623451693
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Naturalnocasecmp To",
	"results": {
		"time": {
			"a": 7.481,
			"b": 8.31,
			"a_div_b": 0.9002406738868832
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Nocasecmp To",
	"results": {
		"time": {
			"a": 30.57,
			"b": 30.56,
			"a_div_b": 1.0003272251308901
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Pad Decimals",
	"results": {
		"time": {
			"a": 264.3,
			"b": 264.5,
			"a_div_b": 0.9992438563327033
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Pad Decimals Pre Constructed",
	"results": {
		"time": {
			"a": 41.05,
			"b": 40.59,
			"a_div_b": 1.011332840601133
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Pad Zeros",
	"results": {
		"time": {
			"a": 179.2,
			"b": 176.9,
			"a_div_b": 1.0130016958733747
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Pad Zeros Pre Constructed",
	"results": {
		"time": {
			"a": 108.7,
			"b": 107.9,
			"a_div_b": 1.0074142724745134
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Rfind",
	"results": {
		"time": {
			"a": 28.02,
			"b": 27.88,
			"a_div_b": 1.0050215208034434
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Rfindn",
	"results": {
		"time": {
			"a": 140.7,
			"b": 140.6,
			"a_div_b": 1.0007112375533427
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Rpad",
	"results": {
		"time": {
			"a": 90.68,
			"b": 92.77,
			"a_div_b": 0.9774711652473861
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Rsplit",
	"results": {
		"time": {
			"a": 216.2,
			"b": 222.2,
			"a_div_b": 0.972997299729973
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Similarity",
	"results": {
		"time": {
			"a": 14.56,
			"b": 16.1,
			"a_div_b": 0.9043478260869565
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Simplify Path",
	"results": {
		"time": {
			"a": 672.5,
			"b": 671.9,
			"a_div_b": 1.0008929900282781
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Split",
	"results": {
		"time": {
			"a": 242.0,
			"b": 236.2,
			"a_div_b": 1.0245554614733277
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Split Floats",
	"results": {
		"time": {
			"a": 150.0,
			"b": 150.3,
			"a_div_b": 0.998003992015968
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Substr",
	"results": {
		"time": {
			"a": 30.77,
			"b": 30.82,
			"a_div_b": 0.9983776768332252
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Camel Case",
	"results": {
		"time": {
			"a": 397.3,
			"b": 398.3,
			"a_div_b": 0.9974893296510168
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Lower",
	"results": {
		"time": {
			"a": 130.8,
			"b": 130.8,
			"a_div_b": 1
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Pascal Case",
	"results": {
		"time": {
			"a": 703.0,
			"b": 694.9,
			"a_div_b": 1.0116563534321485
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Snake Case",
	"results": {
		"time": {
			"a": 558.7,
			"b": 562.1,
			"a_div_b": 0.9939512542252269
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Utf 16 Buffer",
	"results": {
		"time": {
			"a": 68.53,
			"b": 67.18,
			"a_div_b": 1.0200952664483476
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Utf 32 Buffer",
	"results": {
		"time": {
			"a": 46.66,
			"b": 45.62,
			"a_div_b": 1.0227970188513809
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Utf 8 Buffer",
	"results": {
		"time": {
			"a": 65.72,
			"b": 65.99,
			"a_div_b": 0.9959084709804517
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "To Wchar Buffer",
	"results": {
		"time": {
			"a": 45.43,
			"b": 46.53,
			"a_div_b": 0.9763593380614657
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Uri Decode",
	"results": {
		"time": {
			"a": 200.4,
			"b": 203.6,
			"a_div_b": 0.9842829076620826
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Uri Encode",
	"results": {
		"time": {
			"a": 213.9,
			"b": 222.7,
			"a_div_b": 0.9604849573417154
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Validate Filename",
	"results": {
		"time": {
			"a": 192.1,
			"b": 192.3,
			"a_div_b": 0.9989599583983358
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Validate Node Name",
	"results": {
		"time": {
			"a": 55.0,
			"b": 57.88,
			"a_div_b": 0.9502418797512093
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Xml Escape",
	"results": {
		"time": {
			"a": 190.4,
			"b": 192.0,
			"a_div_b": 0.9916666666666667
		}
	}
}
{
	"category": "Gdscript > String Manipulation",
	"name": "Xml Unescape",
	"results": {
		"time": {
			"a": 35.87,
			"b": 36.33,
			"a_div_b": 0.9873382879163226
		}
	}
}
{
	"category": "Gui > Label",
	"name": "Label",
	"results": {
		"render_cpu": {
			"a": 0.3037,
			"b": 0.3044,
			"a_div_b": 0.9977003942181341
		},
		"render_gpu": {
			"a": 0.1663,
			"b": 0.1667,
			"a_div_b": 0.9976004799040193
		},
		"time": {
			"a": 0.109,
			"b": 0.078,
			"a_div_b": 1.3974358974358974
		}
	}
}
{
	"category": "Gui > Label",
	"name": "Label Autowrap Arbitrary",
	"results": {
		"render_cpu": {
			"a": 0.3035,
			"b": 0.3007,
			"a_div_b": 1.0093116062520784
		},
		"render_gpu": {
			"a": 0.1566,
			"b": 0.1564,
			"a_div_b": 1.0012787723785166
		},
		"time": {
			"a": 0.085,
			"b": 0.074,
			"a_div_b": 1.1486486486486487
		}
	}
}
{
	"category": "Gui > Label",
	"name": "Label Autowrap Smart",
	"results": {
		"render_cpu": {
			"a": 0.2994,
			"b": 0.3206,
			"a_div_b": 0.933873986275733
		},
		"render_gpu": {
			"a": 0.1565,
			"b": 0.1564,
			"a_div_b": 1.0006393861892582
		},
		"time": {
			"a": 0.069,
			"b": 0.073,
			"a_div_b": 0.9452054794520549
		}
	}
}
{
	"category": "Gui > Label",
	"name": "Label Autowrap Word",
	"results": {
		"render_cpu": {
			"a": 0.3039,
			"b": 0.3209,
			"a_div_b": 0.947023995014023
		},
		"render_gpu": {
			"a": 0.1565,
			"b": 0.1564,
			"a_div_b": 1.0006393861892582
		},
		"time": {
			"a": 0.107,
			"b": 0.073,
			"a_div_b": 1.4657534246575343
		}
	}
}
{
	"category": "Gui > Label",
	"name": "Label Resize",
	"results": {
		"render_cpu": {
			"a": 0.3021,
			"b": 0.3216,
			"a_div_b": 0.939365671641791
		},
		"render_gpu": {
			"a": 0.4388,
			"b": 0.4378,
			"a_div_b": 1.0022841480127913
		},
		"time": {
			"a": 0.094,
			"b": 0.068,
			"a_div_b": 1.3823529411764706
		}
	}
}
{
	"category": "Gui > Label",
	"name": "Rich Text Label",
	"results": {
		"render_cpu": {
			"a": 0.7392,
			"b": 0.7611,
			"a_div_b": 0.9712258573117856
		},
		"render_gpu": {
			"a": 0.2259,
			"b": 0.2267,
			"a_div_b": 0.996471107190119
		},
		"time": {
			"a": 0.233,
			"b": 0.136,
			"a_div_b": 1.713235294117647
		}
	}
}
{
	"category": "Math > Convex Hull 3d",
	"name": "Both Clean And Simplify",
	"results": {
		"time": {
			"a": 2514.0,
			"b": 2557.0,
			"a_div_b": 0.9831834180680485
		}
	}
}
{
	"category": "Math > Convex Hull 3d",
	"name": "Only Clean",
	"results": {
		"time": {
			"a": 2522.0,
			"b": 2520.0,
			"a_div_b": 1.0007936507936508
		}
	}
}
{
	"category": "Math > Convex Hull 3d",
	"name": "Only Simplify",
	"results": {
		"time": {
			"a": 11.16,
			"b": 14.37,
			"a_div_b": 0.7766179540709812
		}
	}
}
{
	"category": "Math > Convex Hull 3d",
	"name": "Quickest",
	"results": {
		"time": {
			"a": 9.942,
			"b": 8.04,
			"a_div_b": 1.2365671641791047
		}
	}
}
{
	"category": "Math > Delaunay 2d",
	"name": "Delaunay 2d",
	"results": {
		"time": {
			"a": 66.04,
			"b": 67.39,
			"a_div_b": 0.9799673542068557
		}
	}
}
{
	"category": "Math > Delaunay 3d",
	"name": "Delaunay 3d",
	"results": {
		"time": {
			"a": 345.0,
			"b": 398.2,
			"a_div_b": 0.8663987945755902
		}
	}
}
{
	"category": "Math > Expression",
	"name": "Parse 20 Complex Expressions Cold",
	"results": {
		"time": {
			"a": 224.0,
			"b": 219.6,
			"a_div_b": 1.0200364298724955
		}
	}
}
{
	"category": "Math > Expression",
	"name": "Parse 20 Complex Expressions With Cached Parse",
	"results": {
		"time": {
			"a": 217.0,
			"b": 218.7,
			"a_div_b": 0.9922267946959306
		}
	}
}
{
	"category": "Math > Expression",
	"name": "Parse 20 Complex Expressions With Cached Parse Then Execute",
	"results": {
		"time": {
			"a": 224.0,
			"b": 221.4,
			"a_div_b": 1.011743450767841
		}
	}
}
{
	"category": "Math > Noise",
	"name": "Cellular",
	"results": {
		"time": {
			"a": 446.5,
			"b": 447.3,
			"a_div_b": 0.9982114911692376
		}
	}
}
{
	"category": "Math > Noise",
	"name": "Perlin",
	"results": {
		"time": {
			"a": 214.3,
			"b": 213.1,
			"a_div_b": 1.005631159080244
		}
	}
}
{
	"category": "Math > Noise",
	"name": "Simplex",
	"results": {
		"time": {
			"a": 244.5,
			"b": 244.2,
			"a_div_b": 1.0012285012285014
		}
	}
}
{
	"category": "Math > Noise",
	"name": "Simplex Smooth",
	"results": {
		"time": {
			"a": 297.3,
			"b": 299.2,
			"a_div_b": 0.993649732620321
		}
	}
}
{
	"category": "Math > Noise",
	"name": "Value",
	"results": {
		"time": {
			"a": 200.5,
			"b": 199.1,
			"a_div_b": 1.0070316423907584
		}
	}
}
{
	"category": "Math > Noise",
	"name": "Value Cubic",
	"results": {
		"time": {
			"a": 467.3,
			"b": 475.0,
			"a_div_b": 0.9837894736842105
		}
	}
}
{
	"category": "Math > Triangulate",
	"name": "Triangulate",
	"results": {
		"time": {
			"a": 44.76,
			"b": 44.19,
			"a_div_b": 1.012898845892736
		}
	}
}
{
	"category": "Navigation > Astar 2d",
	"name": "Astar 5000 Times 5000 Points",
	"results": {
		"time": {
			"a": 356.6,
			"b": 358.0,
			"a_div_b": 0.9960893854748604
		}
	}
}
{
	"category": "Navigation > Astar 3d",
	"name": "Astar 1000 Times 1000 Points",
	"results": {
		"time": {
			"a": 331.0,
			"b": 331.2,
			"a_div_b": 0.9993961352657005
		}
	}
}
{
	"category": "Navigation > Moving Agents 2d",
	"name": "1000 Moving Agents",
	"results": {
		"render_cpu": {
			"a": 0.03362,
			"b": 0.02958,
			"a_div_b": 1.1365787694388099
		},
		"time": {
			"a": 0.015,
			"b": 0.012,
			"a_div_b": 1.25
		}
	}
}
{
	"category": "Navigation > Moving Agents 3d",
	"name": "1000 Moving Agents",
	"results": {
		"render_cpu": {
			"a": 0.007602,
			"b": 0.007077,
			"a_div_b": 1.0741839762611276
		},
		"time": {
			"a": 0.042,
			"b": 0.087,
			"a_div_b": 0.48275862068965525
		}
	}
}
{
	"category": "Navigation > Navigation 2d",
	"name": "Navigation 10 000 Random Paths",
	"results": {
		"time": {
			"a": 4.284,
			"b": 7.295,
			"a_div_b": 0.587251542152159
		}
	}
}
{
	"category": "Navigation > Navigation 3d",
	"name": "Navigation 10 000 Random Paths",
	"results": {
		"time": {
			"a": 4.666,
			"b": 3.744,
			"a_div_b": 1.2462606837606838
		}
	}
}
{
	"category": "Physics > Area 2d",
	"name": "1000 Area 2d",
	"results": {
		"idle": {
			"a": 32.06,
			"b": 21.25,
			"a_div_b": 1.5087058823529413
		},
		"physics": {
			"a": 27.35,
			"b": 26.44,
			"a_div_b": 1.0344175491679275
		},
		"time": {
			"a": 0.08,
			"b": 0.039,
			"a_div_b": 2.0512820512820515
		}
	}
}
{
	"category": "Physics > Area 3d",
	"name": "1000 Area 3d",
	"results": {
		"idle": {
			"a": 190.5,
			"b": 191.1,
			"a_div_b": 0.9968602825745683
		},
		"physics": {
			"a": 26.33,
			"b": 29.61,
			"a_div_b": 0.8892266126308679
		},
		"time": {
			"a": 0.189,
			"b": 0.772,
			"a_div_b": 0.24481865284974094
		}
	}
}
{
	"category": "Physics > Character Body 2d",
	"name": "1000 Character Bodies 2d",
	"results": {
		"idle": {
			"a": 125.0,
			"b": 128.8,
			"a_div_b": 0.9704968944099378
		},
		"physics": {
			"a": 31.63,
			"b": 29.57,
			"a_div_b": 1.0696652012174501
		},
		"time": {
			"a": 2.4,
			"b": 2.508,
			"a_div_b": 0.9569377990430622
		}
	}
}
{
	"category": "Physics > Character Body 3d",
	"name": "1000 Character Bodies 3d",
	"results": {
		"idle": {
			"a": 358.6,
			"b": 20.79,
			"a_div_b": 17.24867724867725
		},
		"physics": {
			"a": 44.52,
			"b": 48.97,
			"a_div_b": 0.909128037574025
		},
		"time": {
			"a": 0.079,
			"b": 0.044,
			"a_div_b": 1.7954545454545456
		}
	}
}
{
	"category": "Physics > Raycast 2d",
	"name": "10 000 Raycast 2d",
	"results": {
		"time": {
			"a": 27.99,
			"b": 27.48,
			"a_div_b": 1.0185589519650655
		}
	}
}
{
	"category": "Physics > Raycast 3d",
	"name": "10 000 Raycast 3d",
	"results": {
		"time": {
			"a": 305.3,
			"b": 304.9,
			"a_div_b": 1.001311905542801
		}
	}
}
{
	"category": "Physics > Rigid Body 2d",
	"name": "2000 Rigid Body 2d Circles",
	"results": {
		"idle": {
			"a": 305.8,
			"b": 305.4,
			"a_div_b": 1.0013097576948267
		},
		"physics": {
			"a": 40.45,
			"b": 41.32,
			"a_div_b": 0.978944820909971
		},
		"time": {
			"a": 6.846,
			"b": 6.81,
			"a_div_b": 1.005286343612335
		}
	}
}
{
	"category": "Physics > Rigid Body 2d",
	"name": "2000 Rigid Body 2d Continuous",
	"results": {
		"idle": {
			"a": 67.96,
			"b": 46.94,
			"a_div_b": 1.447805709416276
		},
		"physics": {
			"a": 35.98,
			"b": 35.34,
			"a_div_b": 1.0181097906055459
		},
		"time": {
			"a": 7.058,
			"b": 7.692,
			"a_div_b": 0.9175767030681227
		}
	}
}
{
	"category": "Physics > Rigid Body 2d",
	"name": "2000 Rigid Body 2d Mixed",
	"results": {
		"idle": {
			"a": 67.12,
			"b": 52.8,
			"a_div_b": 1.2712121212121215
		},
		"physics": {
			"a": 37.21,
			"b": 37.62,
			"a_div_b": 0.9891015417331208
		},
		"time": {
			"a": 8.029,
			"b": 8.542,
			"a_div_b": 0.9399438070709436
		}
	}
}
{
	"category": "Physics > Rigid Body 2d",
	"name": "2000 Rigid Body 2d Squares",
	"results": {
		"idle": {
			"a": 55.34,
			"b": 55.89,
			"a_div_b": 0.9901592413669709
		},
		"physics": {
			"a": 38.42,
			"b": 43.84,
			"a_div_b": 0.8763686131386861
		},
		"time": {
			"a": 7.622,
			"b": 11.86,
			"a_div_b": 0.642664418212479
		}
	}
}
{
	"category": "Physics > Rigid Body 2d",
	"name": "2000 Rigid Body 2d Unbound",
	"results": {
		"idle": {
			"a": 67.6,
			"b": 65.72,
			"a_div_b": 1.0286062081558125
		},
		"physics": {
			"a": 39.31,
			"b": 36.81,
			"a_div_b": 1.0679163270850311
		},
		"time": {
			"a": 8.083,
			"b": 7.813,
			"a_div_b": 1.0345577883015487
		}
	}
}
{
	"category": "Physics > Rigid Body 2d",
	"name": "2000 Rigid Body 2d Unique",
	"results": {
		"idle": {
			"a": 14.7,
			"b": 14.68,
			"a_div_b": 1.0013623978201636
		},
		"physics": {
			"a": 35.82,
			"b": 35.05,
			"a_div_b": 1.0219686162624824
		},
		"time": {
			"a": 8.079,
			"b": 8.018,
			"a_div_b": 1.007607882264904
		}
	}
}
{
	"category": "Physics > Rigid Body 3d",
	"name": "2000 Rigid Body 3d Boxes",
	"results": {
		"idle": {
			"a": 54.61,
			"b": 56.24,
			"a_div_b": 0.9710170697012802
		},
		"physics": {
			"a": 46.97,
			"b": 49.9,
			"a_div_b": 0.9412825651302605
		},
		"time": {
			"a": 6.179,
			"b": 5.997,
			"a_div_b": 1.030348507587127
		}
	}
}
{
	"category": "Physics > Rigid Body 3d",
	"name": "2000 Rigid Body 3d Continuous",
	"results": {
		"idle": {
			"a": 27.86,
			"b": 28.1,
			"a_div_b": 0.991459074733096
		},
		"physics": {
			"a": 54.5,
			"b": 53.44,
			"a_div_b": 1.0198353293413174
		},
		"time": {
			"a": 6.553,
			"b": 9.753,
			"a_div_b": 0.6718958269250487
		}
	}
}
{
	"category": "Physics > Rigid Body 3d",
	"name": "2000 Rigid Body 3d Mixed",
	"results": {
		"idle": {
			"a": 22.8,
			"b": 27.16,
			"a_div_b": 0.8394698085419735
		},
		"physics": {
			"a": 50.46,
			"b": 49.76,
			"a_div_b": 1.0140675241157557
		},
		"time": {
			"a": 6.703,
			"b": 6.36,
			"a_div_b": 1.0539308176100628
		}
	}
}
{
	"category": "Physics > Rigid Body 3d",
	"name": "2000 Rigid Body 3d Spheres",
	"results": {
		"idle": {
			"a": 27.75,
			"b": 28.47,
			"a_div_b": 0.9747102212855638
		},
		"physics": {
			"a": 58.45,
			"b": 47.11,
			"a_div_b": 1.2407132243684993
		},
		"time": {
			"a": 6.142,
			"b": 6.284,
			"a_div_b": 0.9774029280712923
		}
	}
}
{
	"category": "Physics > Rigid Body 3d",
	"name": "2000 Rigid Body 3d Unbound",
	"results": {
		"idle": {
			"a": 29.01,
			"b": 24.36,
			"a_div_b": 1.1908866995073892
		},
		"physics": {
			"a": 37.44,
			"b": 35.46,
			"a_div_b": 1.0558375634517765
		},
		"time": {
			"a": 6.358,
			"b": 6.289,
			"a_div_b": 1.0109715376053428
		}
	}
}
{
	"category": "Physics > Rigid Body 3d",
	"name": "2000 Rigid Body 3d Unique",
	"results": {
		"idle": {
			"a": 16.73,
			"b": 26.39,
			"a_div_b": 0.6339522546419099
		},
		"physics": {
			"a": 48.05,
			"b": 51.86,
			"a_div_b": 0.9265329733898958
		},
		"time": {
			"a": 11.36,
			"b": 20.0,
			"a_div_b": 0.568
		}
	}
}
{
	"category": "Physics > Softbody 3d",
	"name": "Softbody 3d 500 Rigidbodies",
	"results": {
		"idle": {
			"a": 43.1,
			"b": 28.77,
			"a_div_b": 1.4980882864094545
		},
		"physics": {
			"a": 41.61,
			"b": 35.81,
			"a_div_b": 1.1619659313041049
		},
		"time": {
			"a": 0.045,
			"b": 0.05,
			"a_div_b": 0.8999999999999999
		}
	}
}
{
	"category": "Physics > Triangle Mesh",
	"name": "Triangle Mesh 3d 1000 Rigidbodies",
	"results": {
		"idle": {
			"a": 11.7,
			"b": 13.44,
			"a_div_b": 0.8705357142857143
		},
		"physics": {
			"a": 11.07,
			"b": 13.38,
			"a_div_b": 0.827354260089686
		},
		"time": {
			"a": 0.059,
			"b": 0.266,
			"a_div_b": 0.22180451127819548
		}
	}
}
{
	"category": "Scene Nodes > Add Children",
	"name": "Add Children With Same Name",
	"results": {
		"time": {
			"a": 43.68,
			"b": 52.04,
			"a_div_b": 0.8393543428132206
		}
	}
}
{
	"category": "Scene Nodes > Add Children",
	"name": "Add Children Without Name",
	"results": {
		"time": {
			"a": 41.57,
			"b": 42.98,
			"a_div_b": 0.967194043741275
		}
	}
}
{
	"category": "Scene Nodes > Delete Children",
	"name": "Delete Children In Order",
	"results": {
		"time": {
			"a": 3.502,
			"b": 3.581,
			"a_div_b": 0.977939123149958
		}
	}
}
{
	"category": "Scene Nodes > Delete Children",
	"name": "Delete Children Random Order",
	"results": {
		"time": {
			"a": 10.93,
			"b": 11.03,
			"a_div_b": 0.9909338168631007
		}
	}
}
{
	"category": "Scene Nodes > Delete Children",
	"name": "Delete Children Reverse Order",
	"results": {
		"time": {
			"a": 3.378,
			"b": 5.226,
			"a_div_b": 0.6463834672789897
		}
	}
}
{
	"category": "Scene Nodes > Get Node",
	"name": "Get Node",
	"results": {
		"time": {
			"a": 22.97,
			"b": 22.12,
			"a_div_b": 1.0384267631103072
		}
	}
}
{
	"category": "Scene Nodes > Move Children",
	"name": "Move Children",
	"results": {
		"time": {
			"a": 342.8,
			"b": 354.4,
			"a_div_b": 0.9672686230248307
		}
	}
}
{
	"category": "Viewport > Activation",
	"name": "Activate 1024 Viewports",
	"results": {
		"time": {
			"a": 70.37,
			"b": 70.0,
			"a_div_b": 1.0052857142857143
		}
	}
}
{
	"category": "Viewport > Activation",
	"name": "Activate 256 Viewports",
	"results": {
		"time": {
			"a": 24.73,
			"b": 25.11,
			"a_div_b": 0.9848665870171247
		}
	}
}
{
	"category": "Viewport > Activation",
	"name": "Activate 64 Viewports",
	"results": {
		"time": {
			"a": 5.934,
			"b": 5.982,
			"a_div_b": 0.9919759277833501
		}
	}
}
{
	"category": "Viewport > Allocation",
	"name": "Create 1024 Viewports",
	"results": {
		"time": {
			"a": 34.34,
			"b": 34.88,
			"a_div_b": 0.9845183486238532
		}
	}
}
{
	"category": "Viewport > Allocation",
	"name": "Create 256 Viewports",
	"results": {
		"time": {
			"a": 17.62,
			"b": 12.85,
			"a_div_b": 1.3712062256809339
		}
	}
}
{
	"category": "Viewport > Allocation",
	"name": "Create 64 Viewports",
	"results": {
		"time": {
			"a": 2.379,
			"b": 1.83,
			"a_div_b": 1.3
		}
	}
}

On all benchmarks, a_div_b averages 1.07, which means this PR is slightly faster overall.

@clayjohn
Copy link
Member

clayjohn commented Jan 9, 2025

The physics benchmarks are a little distressing "Physics > Triangle Mesh" has an "a_dev_b" of 0.22. Is that benchmark reproducible?

@Calinou
Copy link
Member

Calinou commented Jan 9, 2025

The physics benchmarks are a little distressing "Physics > Triangle Mesh" has an "a_dev_b" of 0.22. Is that benchmark reproducible?

Unfortunately, no for two reasons:

  • There is no good way to get the time spent in the last frame processing physics, so I have to get the highest value coming from the Performance singleton (updated every second). This is the largest reason why physics benchmarks vary so much across runs - I only have a handful of values I can sample in the run which lasts 10 seconds for each physics test.
    • I might look into tackling this soon.
  • The physics engine isn't deterministic, so there will always be a small variance as the total number of collisions that occur during the runtime will vary across runs. Doing multiple independent runs of each physics benchmark and averaging them can help against that, but it's not implemented in godot-benchmarks yet.
    • We can improve the physics engine to be more deterministic than it is now (like this), even if it won't be 100% deterministic. Note that godot-benchmarks doesn't use Jolt yet, so I don't know if it's more or less deterministic than GodotPhysics. It should be possible to set up a test project to check this.

However, this large difference was seen on the time1 part of that benchmark, which tracks scene loading time, not actual physics processing time. This part is actually decently reproducible, but scene loading on this test is rather quick so it's hard to tell whether it's a definitive regression or not.

Footnotes

  1. This is displayed as Main Thread Time in the godot-benchmarks UI.

core/templates/local_vector.h Outdated Show resolved Hide resolved
core/templates/local_vector.h Show resolved Hide resolved
@Nazarwadim Nazarwadim force-pushed the LocalVector_use_1.5x_growth_factor branch from 77217fe to 6609caf Compare January 10, 2025 14:01
Copy link
Contributor

@Ivorforce Ivorforce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking a lot better now! I'm lifting my NAK since the regression was fixed. I still have some style comments though.

capacity = p_size;
} else {
capacity = MAX((U)2, capacity + ((1 + capacity) >> 1));
if (p_size > capacity) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is always true since you already tested this above. If it weren't true after the new capacity was found you'd get memory issues anyway, lol.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. If we expand from 12 to 13 elements, then this condition will be false because 12 * 1.5 = 18; 12 > 18 == false.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah... I'm just now seeing that your implementation is different than I had thought it is.
The previous implementation used to grow to the nearest power of 2 of the requested size.
You implementation grows to 1.5x the previous capacity, and grows tightly to exactly the requested size if this exceeds the 1.5x growth.

I'm not sure which is better, tbh. I can imagine arguments for either implementation. But this is definitely a change of behavior that goes beyond the 1.5x growth factor instead of 2x.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nazarwadim This is the one I meant, it definitely warrants discussion before a merge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what's wrong with my implementation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a change of behavior, as explained above.
Specifically, your implementation will be slower if reserve is called and more elements are added than reserved for, and slightly faster otherwise.
This may be a trade-off worth making, but I'm not sure it's appropriate for this PR. If it's possible with a 1.5x growth factor, I would keep it agnostic and use the same behavior as before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, your implementation will be slower if reserve is called and more elements are added than reserved for.

In the engine this behavior is almost nowhere and this situation is unlikely.
Due to the fact that less memory is used, the memory is more compact next to each other, which increases the probability that during the reserve we will allocate cached memory, and not cold from the OS.

Copy link
Contributor

@Ivorforce Ivorforce Jan 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the engine this behavior is almost nowhere

I assume you went through the codebase and checked all reserve calls to see if this claim is actually true? :)

Anyway, I have thought about the problem some more. Unfortunately, finding the 'next power of 1.5x' is a little bit harder than finding the next of 2x, so it would be a bit more complex to implement than what you have (probably with a little loop). The speed difference would likely be negligible for most scenarios.
I think it would be ok to just cap it at the requested size, as you have proposed. But I'd like to hear one or two more voices before I feel comfortable giving this PR a final thumbs up.

core/templates/local_vector.h Show resolved Hide resolved
@Ivorforce
Copy link
Contributor

Ivorforce commented Jan 10, 2025

@Nazarwadim Please stop resolving discussions without me actively acknowledging it's been resolved.
Specifically, I consider the one about tight growth to not be resolved yet.

@Nazarwadim
Copy link
Contributor Author

Sorry, ok. I thought it was resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants